<template>
  <div>
    <avue-crud
      ref="crud"
      v-model:search="formSearch"
      v-model:page="tablePage"
      :data="tableData"
      :option="crudOptions"
      style="padding: 15px 20px"
      :table-loading="tableLoading"
      @search-change="searchDataList"
      @search-reset="resetDataList"
      @selection-change="selectionChange"
      @on-load="searchByPage"
    >
      <!-- <template #menu-left>
        <add-button
          v-if="operateButtons.addBtn"
          @click="handleAddDialog"
          :roleType="['app']"
          style="background-color: #3cc393"
        />
        <delete-button
          v-if="operateButtons.delBtn"
          @click="handleDelete"
          :disabled="multiple"
          :perm="['system:user:delete']"
          style="background-color: #fe5151"
        />
        <import-button
          v-if="operateButtons.importBtn"
          @click="handleImport"
          :roleType="['app']"
          style="background-color: #3cc393"
        />
        <export-button
          v-if="operateButtons.exportBtn"
          @click="handleExport"
          :roleType="['app']"
          style="background-color: #3cc393"
        /> -->
      <!-- <template v-for="(btn, index) in customOuterBtnList" :key="index">
          <custom-button
            ref="customBtn"
            v-bind="btn"
            v-show="btn.isShow"
            @click="customButtonClick(btn, index)"
          />
        </template> -->
      <!-- <el-button
          type="success"
          size="mini"
          v-if="operateButtons.customBtn && customBtn.position == 'outer'"
          @click="customButton"
          :roleType="['app']"
          style="background-color: #3cc393; border: none"
          >{{ buttonName }}</el-button
        >
          style="background-color: #3CC393;border:none"
          >{{ customBtn.buttonName }}</el-button
        > -->
      <!-- </template> -->
      <template #menu="{ row }">
        <template v-for="(btn, idx) in customInnerBtnList" :key="idx">
          <custom-button
            ref="customBtn"
            v-bind="btn"
            v-show="btn.isShow"
            @click="customButtonClick(btn, idx, row)"
          />
        </template>
        <text-detail-button
          v-if="operateButtons.viewBtn"
          @click="handleView(row)"
          :roleType="['app']"
          style="color: #3cc393"
        />
      </template>
    </avue-crud>
  </div>
</template>

<script>
import { getToken } from '@/utils/auth'
import { getDicts } from '@base/api/base/dict/data'
import {
  searchPage,
} from '../../../api/model'
import {
  search,
  selectByIdWithSub,
  insertWithSub,
  deleteByIdsWithSub,
  updateByIdWithSub
} from '../../../api/model/apply'
import { debounceWrapper } from '@/utils/zmids'
import {
  handleFormDataTransBack,
  handleFormDataTrans
} from '../../../utils/common-methods'
import customButton from '../../../components/customButton/customButton.vue'
import cityJson from '../../../components/citySelector/city-china.json'

export default {
  name: 'CodeFormModelApply',
  components: { customButton },
  mixins: [],
  data() {
    return {
      pkuuidLabel: '', // 现有模型详情id处理
      pkuuidValue: '', // 现有模型详情id处理
      buttonCode: '',
      buttonName: '',
      customBtnList: [],
      customInnerBtnList: [],
      customOuterBtnList: [],
      selectionList: [],
      // 非多个禁用
      multiple: true,
      formModelVersionId: '',
      formModelVersionDomain: {},
      formMainEntity: {},
      formMainEntityKey: {},
      formSearch: {},
      tablePage: {},
      tableLoading: false,
      tableData: [],
      crudOptions: {},
      editForm: {},
      operateButtons: {},
      selectUserParam: {},
      selectUserOpen: false,
      recallOpen: false, // 撤回原因弹窗
      recallReason: '', // 撤回原因
      curBusinessItem: {},
      // 用户导入参数
      upload: {
        // 是否显示弹出层（用户导入）
        open: false,
        // 弹出层标题（用户导入）
        title: '',
        // 是否禁用上传
        isUploading: false,
        // 设置上传的请求头部
        headers: { tokenName: 'Bearer ' + getToken() },
        // 上传的地址
        url: import.meta.env.VITE_APP_BASE_API,
        newurl: ''
      },
      valueTypeOptions: {
        string: '',
        array: () => [],
        number: 0,
        datetime: undefined
      },
      watchers: [], //用于控制联动的监听器
      formJsonData: [], // 存储表单渲染json的拷贝值
      curColClass: {},
      cityJson,
      pageVersionId: ''
    }
  },
  computed: {
    // 是否带流程
    withFlow() {
      return this.formModelVersionDomain.withFlow === 'Y'
    },
    optionColumn() {
      let arr = []
      if (
        this.editForm.formJsonOption &&
        this.editForm.formJsonOption.column &&
        this.editForm.formJsonOption.column.length
      ) {
        this.editForm.formJsonOption.column.forEach((item) => {
          if (item.prop.indexOf('special') != -1 || item.widget) {
            arr.push(item)
          }
        })
      }
      return arr
    }
    // 动态生成的插槽
    // customSlots() {
    //   const list = [
    //     'upload',
    //     'imageUpload',
    //     'switch',
    //     'select',
    //     'checkbox',
    //     'radio',
    //     'citySelector'
    //   ]
    //   if (this.editForm.formJsonOption && this.editForm.formJsonOption.column) {
    //     return this.editForm.formJsonOption.column.filter((col) => {
    //       return list.indexOf(col.type) > -1
    //     })
    //   } else {
    //     return []
    //   }
    // }
  },
  created() {
    this.init()
  },
  methods: {
    async init() {
      this.initData()
      await this.getPageVersionId()
      await this.getConfigInfo()
    },
    async getPageVersionId() {
      if (this.$route.query && this.$route.query.pageVersionId) {
        this.pageVersionId = this.$route.query.pageVersionId
      }
    },
    initData() {
      this.pageVersionId = ''
      this.formSearch = {}
      this.tablePage = {
        total: 0, // 总页数
        currentPage: 1, // 当前页数
        pageSize: 10 // 每页显示多少条
      }
      this.tableLoading = false
      this.tableData = []
      this.crudOptions = {
        addBtn: false,
        editBtn: false,
        delBtn: false,
        viewBtn: false,
        importBtn: false,
        exportBtn: false,
        printBtn: false,
        customBtn: false,
        updateBtn: false,
        dialogDrag: true,
        selection: true,
        dialogEscape: false,
        searchMenuSpan: 4,
        column: []
      }
      this.editForm = {
        // 控制 dialog
        open: false,
        // 弹出层标题
        title: '',
        // 是否修改操作
        isModify: false,
        // 修改的行号
        modifyRowIndex: -1,
        // 页面数据
        formData: {},
        // 渲染JSON
        formJsonOption: {
          column: [],
          emptyBtn: false, //隐藏清空按钮
          submitBtn: false
        }
      }
    },
    searchTypeFormat(type) {
      switch (type) {
        case 'varchar':
          return 'input'
        case 'number':
          return 'input'
        case 'select':
          return 'select'
        case 'radio':
          return 'select'
        case 'checkbox':
          return 'select'
      }
    },
    searchSuffix(type) {
      switch (type) {
        case 'LIKE':
          return 'Like'
        case 'EQ':
          return ''
        case 'LEFT_LIKE':
          return 'LLike'
        case 'RIGHT_LIKE':
          return 'RLike'
        case 'BETWEEN':
          return ''
        default:
          return ''
      }
    },
    // 获取页面配置信息
    async getConfigInfo() {
      this.tableLoading = true
      // Form渲染JSON
      var pageInfo = await searchPage(this.pageVersionId)
      // Table列信息
      this.crudOptions.column = []

      // Table行配置
      //   const { tableRowDomain } = pageInfo.data
      //   if (tableRowDomain) {
      //     const { align, selectionPrompt, flipPageSelection } = tableRowDomain
      //     const newRowSetting = {
      //       align,
      //       tip: selectionPrompt == 'Y',
      //       reserveSelection: flipPageSelection == 'Y'
      //     }

      //     this.crudOptions = {
      //       ...this.crudOptions,
      //       ...newRowSetting
      //     }
      //   }
      // 查询列和列表展示列
      if (pageInfo.data.tableColumns && pageInfo.data.tableColumns.length > 0) {
        // isPrimaryKey
        this.pkuuidLabel = pageInfo.data.tableColumns.find(
          (item) => item.isPrimaryKey == 'Y'
        ).formEntityColumnName
        for (let index = 0; index < pageInfo.data.tableColumns.length; index++) {
          const column = pageInfo.data.tableColumns[index]
          await this.generateTableColumn(column, pageInfo)
        }
      }
      // 操作按钮
      if (pageInfo.data.operateButtons && pageInfo.data.operateButtons.length > 0) {
        const buttons = pageInfo.data.operateButtons.filter((e) => 'Y' === e.isEnable)
        for (let index = 0; index < buttons.length; index++) {
          const btn = buttons[index]
          console.log('btn', btn)
          switch (btn.buttonCode) {
            case 'insert':
              this.operateButtons.addBtn = true
              break
            case 'update':
              this.operateButtons.editBtn = true
              break
            case 'delete':
              this.operateButtons.delBtn = true
              break
            case 'view':
              this.operateButtons.viewBtn = true
              break
            case 'import':
              this.operateButtons.importBtn = true
              break
            case 'export':
              this.operateButtons.exportBtn = true
              break
            case 'print':
              this.operateButtons.printBtn = true
              break
            default:
              await this.generateCustomBtn(btn)
              break
          }
        }
      }
      this.tableLoading = false
      // 与数据库匹配：列转驼峰
      if (this.crudOptions.column && this.crudOptions.column.length) {
        for (let index = 0; index < this.crudOptions.column.length; index++) {
          const col = this.crudOptions.column[index]
          col.prop = this.changeCamel(col.prop)
        }
      }

      this.getDataList()
    },
    changeCamel(prop) {
      var newProp = ''
      var splitProp = prop.split('_')
      for (let index = 0; index < splitProp.length; index++) {
        const s = splitProp[index]
        if (s) {
          if (newProp === '') {
            newProp = s.toLowerCase()
          } else {
            newProp += s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase()
          }
        }
      }
      return newProp
    },
    getDataList(form, callback) {
      let params = {}
      if (!form) {
        const { currentPage, pageSize } = this.tablePage
        params = {
          pageNum: currentPage,
          pageSize
        }
      } else {
        params = {
          ...form
        }
      }
      return search(this.formMainEntity.tableName, params).then((res) => {
        this.tableData = res.data.list
        this.handleTableDataTrans(this.tableData)
        this.tablePage.total = res.data.total
        if (callback && typeof callback === 'function') {
          callback()
        }
      })
    },
    searchDataList(form, done) {
      this.crudOptions.column.forEach((item) => {
        if (form[item.prop]) {
          form[item.prop + this.searchSuffix(item.operatorNames)] = form[item.prop]
          if (item.operatorNames == 'BETWEEN') {
            form[item.prop + 'Start'] = form[item.prop][0]
            form[item.prop + 'End'] = form[item.prop][1]
            delete form[item.prop]
          }
          if (this.searchSuffix(item.operatorNames) !== '') {
            delete form[item.prop]
          }
        }
      })
      this.getDataList(form, done)
    },
    searchByPage(pageObj) {
      const { currentPage, pageSize } = pageObj
      const params = {
        ...this.formSearch,
        pageNum: currentPage,
        pageSize
      }
    },
    resetDataList() {
      this.getDataList({})
    },
    selectionChange(list) {
      this.selectionList = list.map((item) => item.pkUuid)
      this.multiple = !list.length
    },
    /** 导入按钮操作 */
    handleImport() {
      this.upload.title = '数据导入'
      this.upload.open = true
    },
    /** 下载模板操作 */
    handleImportTemplate: debounceWrapper(function () {
      this.downloadUrl(`/uni/mda/${this.formMainEntity.tableName}/exportTemplate`)
    }),
    // 文件上传中处理
    handleFileUploadProgress(event, file, fileList) {
      this.upload.isUploading = true
    },
    // 文件上传成功处理
    handleFileSuccess: debounceWrapper(function (response, file, fileList) {
      this.upload.open = false
      this.upload.isUploading = false
      this.$refs.upload.clearFiles()
      this.$alert(response.msg, '导入结果', { dangerouslyUseHTMLString: true })
      // this.initData();
    }),
    handleFileBefore(file) {
      return new Promise((resolve, reject) => {
        // 拼接上传url
        // 此处动态配置action URL
        this.upload.newurl = this.upload.url + `/uni/mda/${this.formMainEntity.tableName}/import`
        // dom上传地址更新完成后，触发上传
        this.$nextTick(() => resolve())
      })
    },
    // 提交上传文件
    submitFileForm() {
      this.$refs.upload.submit()
    },
    /** 导出按钮操作 */
    handleExport() {
      this.downloadUrl(`/uni/mda/${this.formMainEntity.tableName}/export`)
    },
    // 自定义按钮
    async customButtonClick(btn, index, row) {
      if (btn.feature && btn.feature.type == 'ajax') {
        if (btn.position == 'inner') {
          const res = await selectByIdWithSub(this.formMainEntity.tableName, {
            id: row.pkUuid || row[this.pkuuidLabel]
          })
          if (res) {
            const { data } = res
            this.$refs.customBtn[index].btnFunc(data)
          }
        } else {
          const list = []
          const promises = []
          this.selectionList.map((id) => {
            const Promise = selectByIdWithSub(this.formMainEntity.tableName, {
              id
            }).then((res) => {
              if (res) {
                const { data } = res
                list.push(data)
              }
            })
            promises.push(Promise)
          })
          await Promise.all(promises)
          console.log('list', list)
          // 现在只支持单个数据发送
          if (list.length) {
            this.$refs.customBtn[index].btnFunc(list[0])
          }
        }
      } else {
        this.$refs.customBtn[index].btnFunc()
      }
    },
    // 控制自定义按钮是否显示
    async checkCustomBtnShow(btn) {
      const { condition } = btn
      if (condition) {
        const { conditionType, conditions } = condition
        // 用于存储多个异步调用
        const promises = []
        if (conditions && conditions.length) {
          conditions.map((cdt) => {
            const { prop, operator, value } = cdt
            const key = prop + this.searchSuffix(operator)
            const params = {
              [key]: value
            }
            const Promise = search(this.formMainEntity.tableName, params).then((res) => {
              // 列表有返回值则返回true
              const { list } = res.data
              return !!list.length
            })
            promises.push(Promise)
          })
          const response = await Promise.all(promises)
          console.log('response', response)
          let isShow = false
          // 处理异步调用结果
          if (conditionType == 'any') {
            isShow = response.indexOf(true) > -1
          } else {
            isShow = !(response.indexOf(false) > -1)
          }
          return isShow
        } else {
          return true
        }
      }
    },
    // 处理方法字符串中的=>转义问题
    handleFuncStrTransform(item) {
      const events = ['change', 'click', 'focus', 'blur', 'appendClick', 'control', 'uploadAfter']
      for (let key in item) {
        if (events.indexOf(key) > -1) {
          // 先对str做转义处理
          const str = item[key].replaceAll('&gt;', '>')
          item[key] = eval('(' + str + ')')
        }
      }
    },
    handleRecallOpen(row, index) {
      this.recallOpen = true
      this.curBusinessItem = row
    },
    // 生成自定义按钮
    async generateCustomBtn(btn) {
      const { styles, condition, feature } = btn
      const btnObj = {
        ...btn,
        styles: JSON.parse(styles),
        condition: JSON.parse(condition),
        feature: JSON.parse(feature),
        clickBanned: true
      }
      const isShow = await this.checkCustomBtnShow(btnObj)
      btnObj.isShow = isShow
      if (btnObj.position == 'inner') {
        this.customInnerBtnList.push(btnObj)
      } else if (btnObj.position == 'outer') {
        this.customOuterBtnList.push(btnObj)
      }
    },
    // 根据组件属性渲染列表列
    async generateTableColumn(column, pageInfo) {
      // 从组件json数据中找到对应组件配置,由于列表中会存在系统字段，在表单字段中无法找到对应字段，所以需要处理
      const formJsonCol = this.editForm.formJsonOption.column.find(
        (item) => item.prop === column.formEntityColumnName
      )

      // const labelWidth = this.getLabelWidthByProp(column)
      // 配置带有字典项的组件
      // let dictionary = formJsonCol?.dictionary;
      // let dictionArr;
      // if (dictionary) {
      //   dictionArr = await getDicts(dictionary);
      // }

      // let dictionaryList = formJsonCol?.dictionary
      //   ? dictionArr.data
      //   : formJsonCol?.dicData;

      const searchCol = pageInfo.data.searchColumns.find(
        (item) => item.formEntityColumnName == column.formEntityColumnName
      )

      // todo 这边字段对应到表单组件的对象属性，然后带入部分组件属性，根据需求
      const obj = {
        ...column,
        label: column.formEntityColumnDesc,
        prop: column.formEntityColumnName,
        searchRange: searchCol.operatorNames == 'BETWEEN' ? true : false,
        search: searchCol.isSearchColumn === 'Y',
        fixed: column.isFixed == 'Y',
        searchType: column.uiAdvise == 'date' ? undefined : this.searchTypeFormat(column.uiAdvise),

        type: this.getColumnCompType(column),
        overHidden: true,
        props: formJsonCol ? formJsonCol?.props : undefined,
        dicData: formJsonCol ? formJsonCol.dicData : undefined,
        valueFormat: column.uiAdvise == 'date' ? 'yyyy-MM-dd' : undefined,
        operatorNames: column.operatorNames,
        searchLabelWidth: labelWidth,
        searchSpan: this.getSearchItemSpanByLabel(labelWidth)
      }

      // 对审批状态单独增加字典项
      //   if (column.formEntityColumnName === 'AUDIT_STATUS') {
      //     obj.dicData = [...this.auditStatusDicts]
      //   }

      this.crudOptions.column.push(obj)
    },
    // 获取列表中的组件类型
    getColumnCompType(column) {
      const { uiAdvise } = column
      const list = ['date', 'upload', 'imageUpload']
      if (list.indexOf(uiAdvise) > -1) {
        return uiAdvise
      }
    },
    // 对表格数据处理转化
    handleTableDataTrans(data) {
      // 从组件json找到所有组件prop值与data对应
      data.map((item) => {
        handleFormDataTransBack(this.editForm.formJsonOption.column, item)
      })
    },
    // 处理文件预览,目前只能支持跳转下载
    filePreview(url) {
      // window.open(
      //   "https://view.officeapps.live.com/op/view.aspx?src=" +
      //     encodeURIComponent(url)
      // );
      window.open(url)
    },
    // 处理开关
    handleSwitchChange(value, slot, row) {
      const { label, prop } = slot
      const title = `确定要切换 ${label} 的状态吗？`
      this.$confirm(title, '警告', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(() => {
          const formData = {
            ...row,
            [prop]: value
          }
          const callback = (res) => {
            if (res && res.code == '200') {
              this.msgSuccess('切换成功！')
              this.getDataList()
            }
          }
          this.updateForm(
            this.editForm.formJsonOption,
            formData,
            this.formModelVersionId,
            this.formMainEntity.tableName,
            callback
          )
        })
        .catch((e) => {
          console.log(e)
        })
    },
    // 获取当前字段的值对应的字典配置
    getCurDicItems(value, column) {
      let res = []
      const { showDicColor, dicData, props } = column
      // 区分单选还是多选
      if (value) {
        if (typeof value == 'string') {
          const dict = dicData.find((item) => item[props.value] == value)
          res = [
            {
              // 用于处理某些情况下字典项不存在，比如其他渠道收集来的数据未在字典项中存储的
              label: dict ? dict[props.label] : value,
              color: dict && showDicColor ? dict.color : undefined
            }
          ]
        } else if (value instanceof Array) {
          if (value.length) {
            value.map((v) => {
              const dict = dicData.find((item) => item[props.value] == v)
              res.push({
                label: dict ? dict[props.label] : v,
                color: dict && showDicColor ? dict.color : undefined
              })
            })
          }
        }
      }

      return res
    },
    // 根据组件字段长度自动生成宽度
    getLabelWidthByProp(entity) {
      const label = entity.formEntityColumnDesc
      // console.log("ccc", column);
      const labelLen = label.length
      // 找出中文字符的个数，中文字符相比数字和字母约占两个单位宽度
      const chineseArr = label.match(/[\u4e00-\u9fa5]/g)
      const chineseLen = chineseArr ? chineseArr.length : 0
      // 计算出总的字符串长度单位
      const total = chineseLen * 2 + labelLen - chineseLen

      if (total <= 8) {
        return 80
      } else {
        return total * 10
      }
    },
    // 根据组件标题宽度，对整个搜索项的宽度做自适应适配
    getSearchItemSpanByLabel(width) {
      // 按照计算，以75px作为1span单位
      const mount = Math.floor((width - 80) / 75)
      const span = 6 + mount
      return span
    },
    // 处理城市选择器的回显,一个递归方法，因为可能会有多层
    getCitySeletorEcho(originStr, value) {
      // console.log("city", this.cityJson);
      const cityConfig = this.cityJson.find((city) => city.value == value)
      if (cityConfig) {
        const { label, parent_code } = cityConfig
        const newStr = label + originStr
        if (parent_code) {
          const newOrigin = '-' + newStr
          return this.getCitySeletorEcho(newOrigin, parent_code)
        } else {
          return newStr
        }
      } else {
        return value
      }
    }
  }
}
</script>

<style lang="scss" scoped>
:deep(.el-pagination.is-background .el-pager li:not(.disabled).active) {
  background-color: #3cc393 !important;
  color: #ffffff !important;
}
:deep(.el-button--primary:not(.is-link)) {
  background-color: #3cc393 !important;
  border-color: #3cc393 !important;
}
// :deep.avue-crud__tip {
//   display: none !important;
// }

:deep(.el-collapse-item__wrap) {
  background-color: transparent;
}

:deep(.avue-crud__left) {
  margin-left: 5px;
}

:deep(.el-tag--dark) {
  border-color: transparent;
}
</style>
